#include <stdio.h>
#include <string.h>
#include <libxml/parser.h>
#include <libxml/tree.h>

#define MAX_FUNC_LIST	8192//4096
#define MAX_ATTR_DEPTH	48//24
#define MAX_ATTR_LENGTH	96

FILE *fp1 = 0;

char attr_path[MAX_ATTR_DEPTH][MAX_ATTR_LENGTH];
int  attr_depth = 0;
int  in_node = 0;

#define MAX_OBJ_DEPTH 16
#define MAX_OBJ_PART_LENGTH 64
int  in_model=0;
int depth = 0, last_depth=0;
char *obj_path, *token, *savep;
char obj[MAX_OBJ_DEPTH][MAX_OBJ_PART_LENGTH];
char last_obj[MAX_OBJ_DEPTH][MAX_OBJ_PART_LENGTH];


void print_node_path_list(xmlNode * a_node)
{
    xmlNode *cur_node = NULL;
	xmlChar *attr_type;
	xmlChar *attr_name;
	xmlChar *attr_rw;
	xmlChar *attr_val;
	char tmp[16];
	int i = 0;
	int j = 0;
	int k = 0;
	int diff_level = 0;
	int diff = 0;
	char rw_str[MAX_ATTR_LENGTH]="";


	for (cur_node = a_node; cur_node; cur_node = cur_node->next) 
	{
		//printf("%s\n",cur_node->name);
		if (cur_node->type == XML_ELEMENT_NODE) 
		{
			if (!strcmp(cur_node->name, "model"))
			{
				in_model = 1;
				//printf("Enter Model!\n");
				//fprintf(fp1, "%s\n", "+++++ !!!Enter model +++++");
			}
			else if (!strcmp(cur_node->name, "profile"))
			{
				in_model = 0;
				//printf("Enter Model!\n");
				//fprintf(fp1, "%s\n", "----- !!!End of datamodel -----");
				//fprintf(fp1, "%s\n", "+++++ !!!Enter Profile +++++");
				for(j = depth-1; j >= 0; j--)
				{
					for(i = 0; i < j; i++)
						fprintf(fp1, "%s", "\t");
					fprintf(fp1, "%s", "</node>\n");
				}
				break;
			}
			//fprintf(fp1, "%s\n", cur_node->name);
			if (!strcmp(cur_node->name,"object") && in_model)
			{
				//printf("%s\n",cur_node->name);
				//printf("%s, %s\n", cur_node->name, xmlGetProp(cur_node, "name"));
				//fprintf(fp1, "%s, ", cur_node->name);
				//fprintf(fp1, "%s\n", xmlGetProp(cur_node, "name"));
				
				// Split path into obj parts.
				obj_path = strdup(xmlGetProp(cur_node, "name"));
				depth = 0;
				memset(obj, 0, sizeof(obj));
				while(1)
				{
					token = strtok_r(obj_path, ".", &savep);
					if(token ==NULL)
						break;
					strcpy(obj[depth], token);
					depth++;
					//printf("depth=%d, token=%s\n", depth, token);
					obj_path = NULL;
				}

				// write end flag. </node>
				//if(depth <= last_depth)
				{
					diff = 0;
					diff_level = 0;
					for(i = 0; i < last_depth; i++)
					{
						if(strcmp(last_obj[i], obj[i]))
							diff++;
						if(diff)
							diff_level++;
					}
					//printf("cur_node=%s, diff_level=%d\n", xmlGetProp(cur_node, "name"), diff_level);
							
					for(i = 0; i < diff_level; i++)
					{
						for(j = 0; j < last_depth -1 - i; j++)
							fprintf(fp1, "%s", "\t");
						fprintf(fp1, "%s", "</node>\n");
					}
				/*
					if (!strcmp(last_obj[last_depth-1],"{i}"))
					{
						for(i = 0; i < last_depth-1; i++)
							fprintf(fp1, "%s", "\t");
						fprintf(fp1, "%s", "</node>\n");
						for(i = 0; i < last_depth-2; i++)
							fprintf(fp1, "%s", "\t");
						fprintf(fp1, "%s", "</node>\n");
					}
					else
					{
						for(i = 0; i < last_depth-1; i++)
							fprintf(fp1, "%s", "\t");
						fprintf(fp1, "%s", "</node>\n");
					}
				*/
				}

				// write node.
				if (xmlStrcmp(xmlGetProp(cur_node, "access"), (const xmlChar *)"readWrite"))
					sprintf(rw_str, "%s", "rw='1'");
				else
					sprintf(rw_str, "%s", "rw='0'");
				if (!strcmp(obj[depth-1],"{i}"))
				{
					for(i = 0; i < depth-2; i++)
						fprintf(fp1, "%s", "\t");
					fprintf(fp1, "<node name='%s' ", obj[depth-2]);
					fprintf(fp1, "%s ", rw_str);
					fprintf(fp1, "%s ", "nin='1' il='10'");
					fprintf(fp1, "%s", "type='node'>\n");

					for(i = 0; i < depth-1; i++)
						fprintf(fp1, "%s", "\t");
					fprintf(fp1, "<node name='%s' ", "template");
					fprintf(fp1, "%s ", rw_str);
					fprintf(fp1, "%s ", "nin='0' il='0'");
					fprintf(fp1, "%s", "type='node'>\n");
				}
				else
				{
					for(i = 0; i < depth-1; i++)
						fprintf(fp1, "%s", "\t");
					fprintf(fp1, "<node name='%s' ", obj[depth-1]);
					fprintf(fp1, "%s ", rw_str);
					fprintf(fp1, "%s ", "nin='0' il='0'");
					fprintf(fp1, "%s", "type='node'>\n");
				}
				last_depth = depth;
				memcpy(last_obj, obj, sizeof(obj));
			}
			else if (!strcmp(cur_node->name,"parameter") && in_model)
			{
				//printf("node=%s\n",cur_node->name);
				if (xmlStrcmp(xmlGetProp(cur_node, "name"), (const xmlChar *)NULL))
				{
					//printf("%s\n", xmlGetProp(cur_node, "name"));
					printf("%s, %s\n", cur_node->name, xmlGetProp(cur_node, "name"));
					//fprintf(fp1, "%s, ", cur_node->name);
					//fprintf(fp1, "%s\n", xmlGetProp(cur_node, "name"));
					
					for(i = 0; i < depth; i++)
						fprintf(fp1, "%s", "\t");
					fprintf(fp1, "<node name='%s'", xmlGetProp(cur_node, "name"));
					if (!strcmp(xmlGetProp(cur_node, "access"),"readWrite"))
						fprintf(fp1, "%s ", "rw='1'");
					else
						fprintf(fp1, "%s ", "rw='0'");
					fprintf(fp1, "%s ", "getc='0'");
					fprintf(fp1, "%s ", "noc='0'");
					fprintf(fp1, "%s ", "nocc='0'");
					fprintf(fp1, "%s ", "acl=''");
					//fprintf(fp1, "type='%s' ", "string");
					//fprintf(fp1, "%s", "></node>\n");
				}
			}
			else if (in_model)
			{
				//printf("%s\n",cur_node->name);
				if (!strcmp(cur_node->name, "boolean") || 
					!strcmp(cur_node->name, "string") || 
					!strcmp(cur_node->name, "int") || 
					!strcmp(cur_node->name, "long") || 
					!strcmp(cur_node->name, "unsignedInt") || 
					!strcmp(cur_node->name, "unsignedLong") || 
					!strcmp(cur_node->name, "dateTime") || 
					!strcmp(cur_node->name, "base64") || 
					!strcmp(cur_node->name, "hexBinary"))
				{
					printf("%s\n",cur_node->name);
					fprintf(fp1, "type='%s'", cur_node->name);
					fprintf(fp1, "%s", "></node>\n");
				}
				else if(!strcmp(cur_node->name, "dataType"))
				{
					printf("%s\n",cur_node->name);
					fprintf(fp1, "type='%s'", "string");
					fprintf(fp1, "%s", "></node>\n");
				}
				//printf("%s\n",cur_node->name);
			}
			
		
		/*
			attr_type = xmlGetProp(cur_node, "type");
			if (!strcmp(attr_type, "node")) 
			{
				attr_name = xmlGetProp(cur_node, "name");
				strcpy(attr_path[attr_depth], (char*)attr_name);
				attr_depth++;
			}		
			else 
			{
				in_node = 1;
				
				for (i=0 ; i<attr_depth ; i++)
				{
					if(!strcmp(attr_path[i], "template"))
						fprintf(fp1, "%s.", "{i}");
					else
						fprintf(fp1, "%s.", attr_path[i]);
				}
				
				attr_name = xmlGetProp(cur_node, "name");
				attr_rw = xmlGetProp(cur_node, "rw");
				//fprintf(fp1, "%s", attr_name);
				//fprintf(fp1, "\n"); 
			}
			attr_depth++;
			if (attr_depth >= MAX_ATTR_DEPTH) 
			{
				printf("Error : Too many layers in Data Model, try increase attribute depth ...! \n");
				exit(1);
			}
			*/
		}
		else if (cur_node->type == XML_TEXT_NODE)
		{
			//printf("%s\n",cur_node->name);
			if (*(cur_node->content) < ' ') 
			{	// </node>
				if (attr_depth) 
					attr_depth--;
				if (in_node) {	
					//fprintf(fp1, "\"\"},\n"); 
					in_node = 0;	
				}
			}
			else 
			{
				if (*(cur_node->content) != '\0') 
				{
					//fprintf(fp1, "\"%s\"},\n", cur_node->content);
					in_node = 0;	
				} 
			}
		}
		print_node_path_list(cur_node->children);
    }
}


int main(int argc, char **argv)
{
    xmlDoc *doc = NULL;
    xmlNode *root_element = NULL;
    int i;

    if (argc != 2)
        return(1);

    LIBXML_TEST_VERSION

    doc = xmlReadFile(argv[1], NULL, 0);
    if (doc == NULL) {
        printf("Error: can not parse file %s\n", argv[1]);
        return(1);
    }

/*
	if(argv[2] != "")
		fp1 = fopen(argv[2], "w");
	else
*/
		//fp1 = fopen("xml_node_list.txt", "w");
		fp1 = fopen("x.xml", "w");
	if (!fp1) {
        printf("Error: can not create file %s\n", "x.xml");
        return(1);
    }
    
    root_element = xmlDocGetRootElement(doc);
    print_node_path_list(root_element);
	fclose(fp1);

	xmlFreeDoc(doc);
	xmlCleanupParser();

	return 0;
}
